package com.zhihuishu.micro.course.service.impl;

import com.zhihuishu.micro.course.dto.CourseDataDto;
import com.zhihuishu.micro.course.helper.LogModule;
import com.zhihuishu.micro.course.helper.RemoteLogHelper;
import com.zhihuishu.micro.course.service.CCDataTreenityDBService;
import com.zhihuishu.micro.course.service.CCDataTreenityRedisService;
import com.zhihuishu.micro.course.service.CCDataTreenityService;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * table-DATA
 * @author Jiangli
 * @date 2016/12/16 13:15
 */
@Service("ccDataTreenityService")
public class CCDataTreenityServiceImpl extends BaseTreenityBatchServiceImpl<CourseDataDto> implements CCDataTreenityService {
    private final static String moduleCN = "cc文件";
    private final static int moduleCode = LogModule.CC_DATA.getCode();

    @Resource
    private CCDataTreenityDBService ccDataTreenityServiceDB;

    @Resource
    private CCDataTreenityRedisService ccDataTreenityServiceRedis;


    @Override
    protected CCDataTreenityDBService getDBService() {
        return ccDataTreenityServiceDB;
    }

    @Override
    protected Class<CourseDataDto> getDTOClass() {
        return CourseDataDto.class;
    }

    @Override
    protected CCDataTreenityRedisService getRedisService() {
        return ccDataTreenityServiceRedis;
    }


    @Override
    public CourseDataDto updateAndGet(CourseDataDto dto, long updateUserId) {
        //unique check
        checkAndGetUniqueName(dto,"update");

        CourseDataDto detailInDB = doUpdate(dto, updateUserId);

        return detailInDB;
    }

    @Override
    public CourseDataDto refreshUniqueName(CourseDataDto dto, long updateUserId) {
        Integer id = dto.getId();
        if(!StringUtils.isEmpty(id)){
            CourseDataDto detail = detail(id);

            String oldName = detail.getName();

            CourseDataDto update = new CourseDataDto();
            update.setId(id);
            update.setName(oldName);

            return updateAndGet(update, updateUserId);
        }

        return dto;
    }

    private CourseDataDto doUpdate(CourseDataDto dto, long updateUserId) {
        Assert.notNull(dto);
        Integer dtoId = dto.getId();
        Assert.notNull(dtoId);

        // 更新数据库中的章
        getDBService().update(dto,updateUserId);

        //直接查库，然后更新缓存
        CourseDataDto detailInDB = getDBService().detail(dtoId);
        log.debug("update {} from params:[{}]!" ,getDTOName(),String.valueOf(dto)) ;
        log.debug("update {} from db:[{}]!" ,getDTOName(),String.valueOf(detailInDB) ) ;

        getRedisService().update(detailInDB,updateUserId);

        log.warn("执行更新dto:[{}]，更新人[{}]!" , dtoId,updateUserId) ;
        return detailInDB;
    }

    /**
     * 前缀唯一
     * @param dto
     * @param mode
     */
    private void checkAndGetUniqueName(CourseDataDto dto, String mode) {
        String oldFileName = dto.getName();

        if(!StringUtils.isEmpty(oldFileName)){
            String oldFilePrefix = oldFileName.substring(0,oldFileName.lastIndexOf("."));
            String oldFileSuffix = oldFileName.substring(oldFileName.lastIndexOf(".")+1);

            //查找前缀类似 oldFilePrefix.% 的记录的DATA_NAME字段
            List<String> likeFileNames=null;
            String likePattern = oldFilePrefix+"%";

            if (mode.equals("update")) {
                Long id = dto.getId().longValue();
                likeFileNames = getDBService().findFileNameForUpdate(id,likePattern);
            }
            if (mode.equals("create")) {
                Long id = dto.getFolderId();
                likeFileNames = getDBService().findFileNameForCreate(id,likePattern);
            }

            //过滤特殊情形 - 比如 给定aaa.jpg , aaa.jpg.abc不算前缀重复
            List<String> duplicatePrefix = retainDuplicatePrefix(likeFileNames,oldFilePrefix);

            //1.查看是否满足前缀唯一
            if(duplicatePrefix.size() > 0){
                //1.1若不满足 计算max值
                int max=retainBracketPrefix(likeFileNames,oldFilePrefix);

                //1.2得到新的fileName 并设置到dto中
                String newFileName = oldFilePrefix + "(" + (max + 1) + ")." + oldFileSuffix;
                dto.setName(newFileName);
            }

        }
    }

    //给定abc.jpg  只留下
    //abc.xxxyyy 格式
    private List<String> retainDuplicatePrefix(List<String> likeFileNames, String oldFilePrefix) {
        List<String> ret = new ArrayList<String>(likeFileNames.size());

        for (String one : likeFileNames) {
            try {
                String t = one.substring(oldFilePrefix.length() + 1);
                if(!t.contains(".")){
                    ret.add(t);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return ret;
    }

    //给定abc.jpg  只留下
    //abc(1)
    //abc(2)
    //abc(n) 格式
    private int retainBracketPrefix(List<String> likeFileNames, String oldFilePrefix) {
        int max=0;

        Pattern compile = Pattern.compile("(?<=\\()\\d+(?=\\))");

        for (String one : likeFileNames) {
            try {
                String t = one.substring(oldFilePrefix.length());
                t = t.substring(0,t.indexOf("."));

                Matcher matcher = compile.matcher(t);
                if ( matcher.find()) {
                    String group = matcher.group();

                    Integer current = Integer.parseInt(group);
                    if (current > max) {
                        max = current;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return max;
    }

    @Override
    public Integer create(CourseDataDto dto, long creator) {
        Assert.notNull(dto, moduleCN+"对象为空!");
        Assert.notNull(dto.getOneToManyId(), moduleCN+"所属oneToManyId为空!");
        Assert.notNull(dto.getName(), moduleCN+"的字段-name为空!");

        RemoteLogHelper.log(moduleCode, creator, "[开始]创建"+moduleCN+"[oneToManyId ID：{}/序号：{}]", dto.getOneToManyId(), dto.getRank());

        //unique check
        checkAndGetUniqueName(dto,"create");

        //fixed
        dto.setUserRole(2);
        dto.setCreateTime(new Date());//save to redis
        Integer dtoId = super.create(dto, creator);

        RemoteLogHelper.log(moduleCode, creator
                , "[完成]创建"+moduleCN+"[oneToManyIdID：{}/序号：{}]({})"
                , dto.getOneToManyId(), dto.getRank(), dtoId);
        return dtoId;
    }


    @Override
    protected Comparator<? super CourseDataDto> getDtoListSorter() {
        //按创建时间排序
        return new  Comparator<CourseDataDto>() {
            @Override
            public int compare(CourseDataDto o1, CourseDataDto o2) {
                if(o1 == null || o1.getCreateTime() == null) return 0 ;
                if(o2 == null || o2.getCreateTime() == null) return 0 ;
                return o1.getCreateTime().compareTo(o2.getCreateTime());
            }
        };
    }

    @Override
    public void sort(List<CourseDataDto> dbDtoList, long updateUserId) {
        throw new UnsupportedOperationException("sort is not supported!!!");
    }

    @Override
    public List<CourseDataDto> listByFolderIdsFilterDataType(List<Long> folderIds, String dataType) {
        return getDBService().listByFolderIdsFilterDataType(folderIds, dataType);
    }
}
